use crate::logic::admin::system_admin::SystemAdminService;
use crate::logic::common::cache::CacheService;
use crate::logic::common::captcha::CaptchaService;
use config::config::ApplicationConfig;
use logic::admin::system_admin_auth::SystemAdminAuthService;
use once_cell::sync::Lazy;
use rbatis::RBatis;
use rbdc_mysql::MysqlDriver;

pub mod common;
pub mod config;
pub mod error;
pub mod handle;
pub mod logic;
pub mod middleware;
pub mod model;
pub mod plugin;
pub mod utils;

pub struct ApplicationContext {
    pub config: ApplicationConfig,
    pub db: RBatis,
    pub cache_service: CacheService,
    pub system_admin_auth_service: SystemAdminAuthService,
    pub system_admin_service: SystemAdminService,
    pub captcha_service: CaptchaService,
}

impl Default for ApplicationContext {
    fn default() -> Self {
        let config = ApplicationConfig::default();
        let db = RBatis::new();
        if db.is_debug_mode() == false && config.debug.eq(&true) {
            panic!(r#"please edit config.yml   “debug: false” "#);
        }
        ApplicationContext {
            config: config.clone(),
            db,
            cache_service: CacheService::new(&config).unwrap(),
            system_admin_auth_service: SystemAdminAuthService {},
            system_admin_service: SystemAdminService {},
            captcha_service: CaptchaService {},
        }
    }
}

impl ApplicationContext {
    pub async fn init_db(&self) {
        self.db
            .link(MysqlDriver {}, &self.config.db_url)
            .await
            .expect("db pool connect faild!");
        self.db
            .get_pool()
            .unwrap()
            .set_max_open_conns(self.config.db_pool_len as u64)
            .await;
        //self.db.get_pool().unwrap().set_timeout(Some(Duration::from_secs(self.config.db_pool_timeout as u64))).await;
        log::info!(
            "[ntex_admin] db pool init success! pool state = {}",
            self.db.get_pool().expect("db pool not init!").state().await
        );
        log::info!(
            " - Local:   http://{}",
            self.config.server_url.replace("0.0.0.0", "127.0.0.1")
        );
    }
}

#[macro_export]
macro_rules! db_pool {
    () => {
        &$crate::APPLICATION_CONTEXT.db
    };
}

// 注册APPCLIATION_CONTEXT
pub static APPLICATION_CONTEXT: Lazy<ApplicationContext> =
    Lazy::new(|| ApplicationContext::default());

// 初始化系统配置
pub async fn startup() {
    APPLICATION_CONTEXT.init_db().await;
}
